'use strict';

let redis = require('redis');
let eventEmitter = require('events');
let child_process = require('child_process');

const UNIT_MAP = {
  week: 7 * 24 * 60 * 60 * 1000,
  day: 24 * 60 * 60 * 1000,
  h: 60 * 60 * 1000,
  min: 60 * 1000,
  s: 1000,
};

/**
 * @author xuezi
 */
class SCHEDULED extends eventEmitter {
  /**
   * constructor
   * @param {Object} redisOptions optional {Number} db, optional {String} prefix, and other redis options
   * @return {SCHEDULED}
   */
  constructor(redisOptions) {
    super();
    let self = this;

    // let redis support subscribe key expired event
    child_process.execSync('redis-cli config set notify-keyspace-events Ex');

    // save eventMap to quene
    self.eventMap = new Map();
    // save scheduled Map
    self.scheduledMap = new Map();
    // save scheduled events Map
    self.scheduledEventMap = new Map();

    redisOptions = Object.assign({
      db: 1,
      prefix: 'scheduled'
    }, redisOptions || {});
    self.options = redisOptions;

    let password = redisOptions.auth || redisOptions.auth_pass || redisOptions.password;

    self.redis = redis.createClient(redisOptions);

    if (password) {
      self.redis.auth(password);
    }

    self.redis.on('error', e => {
      if (e) console.error('e', e);
    });
    // when redis connected success, check eventMap quene
    self.redis.on('connect', () => {
      if (self.eventMap.size) {
        self.eventMap.forEach((event, key) => {
          typeof event == 'function' && event();
          self.eventMap.delete(key);
        });
      }
    });

    self.on('eventClear', () => {

    });

    self.scheduledRedis = redis.createClient(redisOptions);

    if (password) {
      self.scheduledRedis.auth(password);
    }

    self.scheduledRedis.psubscribe(`__keyevent@${redisOptions.db||1}__:expired`, (e) => {
      e && console.error(e);
    });
    // when channel publish message, check expire key and event
    self.scheduledRedis.on('pmessage', (channel, listen, key) => {
      (listen == `__keyevent@${self.options.db}__:expired`) && this.emit('pmessage', key.replace(redisOptions.prefix, ''));
    });
  }

  setSchedule(key, time) {
    let timestamp = new Date(time) - new Date;
    if (timestamp < 1000) return console.error('time error');
    this.redis.psetex(key, timestamp, 1, function(err) { console.log(err); });
  }

  onMessage(cb) {
    this.on('pmessage', function(key) {
      cb(key);
    });
  }

  exists(key, cb) {
    this.redis.exists(key, function(err, r) {
      if (r) return cb(true);
      cb();
    });
  }

}


module.exports = SCHEDULED;
